package cn.pli.femedia.video;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.Matrix;
import android.util.Log;
import android.view.Surface;

import cn.pli.femedia.filter.FilterManager;
import cn.pli.femedia.filter.FilterManager.FilterType;
import cn.pli.femedia.gles.FullFrameRect;
import cn.pli.femedia.gles.GlUtil;


public class VideoRecordRender {
    private static final int RECORDING_OFF = 0;         //录制关闭
    private static final int RECORDING_ON = 1;          //录制开始
    private static final int RECORDING_RESUMED = 2;     //重新录制

    private final Context mApplicationContext;
    private int mTextureId = GlUtil.NO_TEXTURE;
    private FullFrameRect mFullScreen;              //绘制
    private SurfaceTexture mSurfaceTexture;         //
    private Surface mSurface;                       //android 的sueface

    private final float[] mSTMatrix = new float[16];    //矩阵
    private FilterType mCurrentFilterType;              //当前滤镜
    private FilterType mNewFilterType;                  //新的滤镜
    private TextureMovieEncoder mVideoEncoder;          //编码器

    private boolean mRecordingEnabled;
    private int mRecordingStatus;
    private EncoderConfig mEncoderConfig;           //编码器配置信息，视频的宽高，码率

    private float mMvpScaleX = 1f, mMvpScaleY = 1f;
    private int mSurfaceWidth, mSurfaceHeight;
    private int mIncomingWidth, mIncomingHeight;

    long lastDecoderTimestamp=0;        //原始帧的时间戳
    long lastEncoderTimestamp=0;        //编码帧时间戳
    float speed=1f;           //播放速度，1为视频速度，0.5为快进1倍，2为慢1倍

    /**
     * 构造方法
     * @param applicationContext
     */
    public VideoRecordRender(Context applicationContext,EncoderConfig encoderConfig) {
        mApplicationContext = applicationContext;
        mCurrentFilterType = mNewFilterType = FilterType.Blend;
        mVideoEncoder = TextureMovieEncoder.getInstance();      //get TextureMovieEncoder's Instance
        this.mEncoderConfig=encoderConfig;

    }

    /**
     * 设置编码器配置信息
     * @param encoderConfig
     */
    public void setEncoderConfig(EncoderConfig encoderConfig) {
        mEncoderConfig = encoderConfig;
    }

    /**
     * 这是编码状态
     * @param recordingEnabled
     */
    public void setRecordingEnabled(boolean recordingEnabled) {
        mRecordingEnabled = recordingEnabled;
    }

    /**
     * 设置原始视频尺寸
     * @param width
     * @param height
     */
    public void setOriginalVideoSize(int width, int height) {
         lastDecoderTimestamp=0;
         lastEncoderTimestamp=0;
        mIncomingWidth = width;
        mIncomingHeight = height;
        float scaleHeight = mSurfaceWidth / (width * 1f / height * 1f);
        float surfaceHeight = mSurfaceHeight;
        if (mFullScreen != null) {
            mMvpScaleX = 1f;
            mMvpScaleY = scaleHeight / surfaceHeight;
            mFullScreen.scaleMVPMatrix(mMvpScaleX, mMvpScaleY);
        }

    }

    /**
     *  视频编辑准备情况
     */
    public void onEditVideoReady() {
       // createEglContext();
        Matrix.setIdentityM(mSTMatrix, 0);
        mRecordingEnabled = mVideoEncoder.isRecording();
        if (mRecordingEnabled) {
            mRecordingStatus = RECORDING_RESUMED;
        } else {
            mRecordingStatus = RECORDING_OFF;
            mVideoEncoder.initFilter(mCurrentFilterType);       //初始化滤镜
        }
        mFullScreen = new FullFrameRect(FilterManager.getCameraFilter(mCurrentFilterType, mApplicationContext));
        mTextureId = mFullScreen.createTexture();
        mSurfaceTexture = new SurfaceTexture(mTextureId);
        mSurface=new Surface(mSurfaceTexture);
    }

    /**
     * 设置视频尺寸
     * @param width
     * @param height
     */
    public void onVideoSizeChanged(int width, int height) {
        mSurfaceWidth = width;
        mSurfaceHeight = height;
    }

    /**
     * 处理视频帧
     */
    public void onDrawFrame() {
        //更新缓存文件
      //  timestamp=timestamp+20000000;



        mSurfaceTexture.updateTexImage();
        if (mNewFilterType != mCurrentFilterType) {
            mFullScreen.changeProgram(FilterManager.getCameraFilter(mNewFilterType, mApplicationContext));
            mCurrentFilterType = mNewFilterType;
        }
        mFullScreen.getFilter().setTextureSize(mIncomingWidth, mIncomingHeight);
        mSurfaceTexture.getTransformMatrix(mSTMatrix);
        Log.d("getTimestamp", "getTimestamp " + mSurfaceTexture.getTimestamp());
        if (lastDecoderTimestamp==0){
            lastDecoderTimestamp=mSurfaceTexture.getTimestamp();
            lastEncoderTimestamp=lastDecoderTimestamp;
        }else{
            long interval=mSurfaceTexture.getTimestamp()-lastDecoderTimestamp;
            lastDecoderTimestamp=mSurfaceTexture.getTimestamp();
            lastEncoderTimestamp+=interval*speed;

        }


        videoOnDrawFrame(mTextureId, mSTMatrix, lastEncoderTimestamp);
    }


    private void videoOnDrawFrame(int textureId, float[] texMatrix, long timestamp) {
        if (mRecordingEnabled && mEncoderConfig != null) {
            switch (mRecordingStatus) {
                case RECORDING_OFF:
                    mEncoderConfig.updateEglContext(EGL14.eglGetCurrentContext());
                    mVideoEncoder.startRecording(mEncoderConfig);           //开始录制视频
                    mVideoEncoder.setTextureId(textureId);                      //设置纹理id
                    mVideoEncoder.scaleMVPMatrix(mMvpScaleX, mMvpScaleY);
                    mRecordingStatus = RECORDING_ON;
                    break;
                case RECORDING_RESUMED:
                    mVideoEncoder.updateSharedContext(EGL14.eglGetCurrentContext());
                    mVideoEncoder.setTextureId(textureId);
                    mVideoEncoder.scaleMVPMatrix(mMvpScaleX, mMvpScaleY);
                    mRecordingStatus = RECORDING_ON;
                    break;
                case RECORDING_ON:
                    break;
                default:
                    throw new RuntimeException("unknown status " + mRecordingStatus);
            }
        } else {
            switch (mRecordingStatus) {
                case RECORDING_ON:
                case RECORDING_RESUMED:
                    mVideoEncoder.stopRecording();
                    mRecordingStatus = RECORDING_OFF;
                    break;
                case RECORDING_OFF:
                    // yay
                    break;
                default:
                    throw new RuntimeException("unknown status " + mRecordingStatus);
            }
        }

        mVideoEncoder.updateFilter(mCurrentFilterType);
        mVideoEncoder.frameAvailable(texMatrix, timestamp);
    }

    public void notifyPausing() {

        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }

        if (mFullScreen != null) {
            mFullScreen.release(false);     // assume the GLSurfaceView EGL context is about
            mFullScreen = null;             // to be destroyed
        }
    }

    public void changeFilter(FilterType filterType) {
        mNewFilterType = filterType;
    }


    public SurfaceTexture getmSurfaceTexture() {
        return mSurfaceTexture;
    }
    public int getmSurfaceHeight() {
        return mSurfaceHeight;
    }
    public int getmSurfaceWidth() {
        return mSurfaceWidth;
    }

    /**
     * 获取surface
     * @return
     */
    public Surface getmSurface(){
        return mSurface;
    }



}
